using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using HardwareInterfaceManagement; // include communications manager
using System.Runtime.Serialization.Formatters.Binary; //
using System.Runtime.Serialization;
using System.IO;
using System.IO.Ports;
using LBSoft.IndustrialCtrls.Leds;
using ZedGraph;
using Microsoft.Win32;

using SimpleMessaging;


namespace FTFSmartCar
{

    public partial class FTFSmartCarInterfaceSurfaceForm : Form
    {
        #region Helper Objects (Communications Manager and Options Form


        public SystemControlForm MySystemControlForm = new SystemControlForm();
        public CommunicationsManager MyCommunicationsManager = new CommunicationsManager(); // make an instance of communications manager
        public BatteryViewerForm MyBatteryViewer = new BatteryViewerForm();
        public ServoControlForm MyServoControlForm = new ServoControlForm();
        public IRSensorViewer MyIRSensorViewer = new IRSensorViewer();
        public RPMViewerForm MyRPMViewer = new RPMViewerForm();
        public IR2d MyIR2d = new IR2d();
        public ControlViewerForm MyControlViewerForm = new ControlViewerForm();

        public FTFSmartCarMessages.PostAutoNVStateVariables MyAutoNVState;

   
        #endregion

        #region Global Variables used by the GUI

        public byte LastPotReading;
        public uint LastRPMReading;

        public String DetectedCOMPort = "";
        int SavedSelectedIndex = 0;
     
        public bool LastStateNoPortFound = true;

        bool FirmwareVersionRecieved = false;

        int CurrentSystemState = -1;

        Thread ProcessMsgThread;

        byte FirmwareVersionMajor = 0;
        byte FirmwareVersionMinor = 0;

        void ResetStateVariables()
        {
            FirmwareVersionRecieved = false;
            FirmwareVersionMajor = 0;
            FirmwareVersionMinor = 0;
            CurrentSystemState = -1;
        }

        double HCS08_BUS_CLK = 19922944 / 2;

        #endregion

        #region GUI Constructor and Startup Code

        void InitControls()
        {
            this.Invalidate();
        }

        public FTFSmartCarInterfaceSurfaceForm()
        {
            InitializeComponent();
            InitControls();
            ResetStateVariables();
            this.
            MySystemControlForm.MdiParent = this;
            MySystemControlForm.Show();

            MyControlViewerForm.MdiParent = this;

            ProcessMsgThread = new Thread(new ThreadStart(ParseIncomingMessages));
            ProcessMsgThread.Start();
            MyServoControlForm.MdiParent = this;
            MyBatteryViewer.MdiParent = this;
            MyIR2d.MdiParent = this;
            MyIRSensorViewer.MdiParent = this;
            MyRPMViewer.MdiParent = this;
        }

        #endregion

        #region GUI CallBacks
      
        private void connectToHardwareToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MySystemControlForm.MsgToTx.Clear();
            ConnectToHardware();
        }
        
        private void GUI_FormClosing(object sender, FormClosingEventArgs e)
        {

        

        }
    
        private void WindowUpdateTimer_Tick(object sender, EventArgs e)
        {
          
            #region FIRMWARE_LABEL
            if (FirmwareVersionRecieved == true)
            {
                MySystemControlForm.FirmwareVersionLabel.Text = "Firwmare Version: " + FirmwareVersionMajor + "." + FirmwareVersionMinor;
            }
            else
            {
                MySystemControlForm.Text = "Firmware Version not recieved.";
            }
            #endregion

            #region SYSTEM STATE LABEL

            switch (CurrentSystemState)
            {
                case FTFSmartCarMessages.SystemStates.SYSTEM_STATE_AUTO_NV:
                    MySystemControlForm.SystemStateLabel.Text = "System State: SYSTEM_STATE_AUTO_NV";
                    break;
               
                case FTFSmartCarMessages.SystemStates.SYSTEM_STATE_IDLE:
                    MySystemControlForm.SystemStateLabel.Text = "System State: SYSTEM_STATE_IDLE";
                    break;
                case FTFSmartCarMessages.SystemStates.SYSTEM_STATE_INIT:
                    MySystemControlForm.SystemStateLabel.Text = "System State: SYSTEM_STATE_INIT";
                    break;
              
                default:
                    MySystemControlForm.SystemStateLabel.Text = "System State: Not Reported.";
                    break;

            }
            #endregion

            #region CONNECTION STATUS LABEL

            if (MyCommunicationsManager.ConnectionActive)
            {
                this.connectToHardwareToolStripMenuItem.Text = "Disconnect From Hardware";
            }
            else
            {
                this.connectToHardwareToolStripMenuItem.Text = "Connect To Hardware";
            }
            // change connection status
            MySystemControlForm.ConnectionStatusLabel.Text = MyCommunicationsManager.ConnectionStatus;
            #endregion

            #region Pot Update

            MySystemControlForm.PotValueLabel.Text = "Current Pot Reading :" + LastPotReading.ToString();

            #endregion

            #region RPM

            MySystemControlForm.RawRPMLabel.Text = "Current RPM Reading :" +String.Format("{0:x8}", LastRPMReading); ;

            #endregion

            if (MyAutoNVState != null)
            {
                MySystemControlForm.PostAutoNVStateVariableHandler(MyAutoNVState);
            }
       
        
        }
       
   

        private void softResetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MyCommunicationsManager.ConnectionActive == true)
            {
                GlobalMessages.SoftwareResetMessage MySoftReset = new GlobalMessages.SoftwareResetMessage();
                MyCommunicationsManager.Write(MySoftReset.ToByteArray());
                ResetStateVariables();
            }
        }
     
        #endregion

        #region Hardware Communications and helper functions

        void ConnectToHardware()
        {
            ResetStateVariables();          
            if (MyCommunicationsManager.ConnectionActive == true)
            {
                Thread.Sleep(250);
                this.UpdateSmartCar.Enabled = false; // turn off update timer 
                MyCommunicationsManager.Close();
            
                
            }
            else
            {
                if ((AvailableCOMPortsCB.Items.Count > 0))
                    {
                        MyCommunicationsManager.COMPort = (string)AvailableCOMPortsCB.SelectedItem;
                    }
                    else
                    {
                        MessageBox.Show( "No Available COM Ports for connection." +
                                               "Try the manual setting in the options panel or recycling the USB cable", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
        
                }

                MyCommunicationsManager.Connect();
             

        }
        
        private void COMDetectTimer_Tick(object sender, EventArgs e)
        {
            if (MyCommunicationsManager.ConnectionActive == false)
            {
                String[] AvailableCOMPorts = SerialPort.GetPortNames();
                if (AvailableCOMPorts.Length == 0)
                {

                    AvailableCOMPortsCB.Items.Clear();
                    AvailableCOMPortsCB.Items.Add("No COM ports found");

             
                    AvailableCOMPortsCB.SelectedIndex = 0;
   
                }
                else
                {
                    if (AvailableCOMPortsCB.SelectedIndex == AvailableCOMPorts.Length)
                        MyCommunicationsManager.UseingTCP = true;

                    SavedSelectedIndex = AvailableCOMPortsCB.SelectedIndex;

                    if (SavedSelectedIndex > (AvailableCOMPorts.Length))
                    {
                        SavedSelectedIndex = (AvailableCOMPorts.Length);
                    }

                    if (SavedSelectedIndex < 0)
                    {
                        SavedSelectedIndex = 0;
                    }

                    AvailableCOMPortsCB.Items.Clear();
                    for (int i = 0; i < AvailableCOMPorts.Length; i++)
                    {
                        AvailableCOMPortsCB.Items.Add(AvailableCOMPorts[i]);
                    }

                    AvailableCOMPortsCB.Items.Add("TCP");

                    AvailableCOMPortsCB.SelectedIndex = SavedSelectedIndex;



                }
            }
            else
            {
          
            }

        }
       
        private void UpdateSmartCar_Tick(object sender, EventArgs e)
        {
            if (MyCommunicationsManager.ConnectionActive == true)
            {

                #region Firmware check
                //see if we have recieved the firmware message, if not keep requesting
                if (FirmwareVersionRecieved == false)
                {
                    GlobalMessages.GetFirmwareMessage MyFirmwareMsg = new GlobalMessages.GetFirmwareMessage();
                    MyCommunicationsManager.Write(MyFirmwareMsg.ToByteArray());
                }

                #endregion

                #region System Control Check

                //see if the system control form needs to send things out

                while(MySystemControlForm.MsgToTx.Count > 0)
                {
                    MyCommunicationsManager.Write(MySystemControlForm.MsgToTx.Dequeue());
                }

                #endregion

                if (MyServoControlForm.ManualServoCommandsEnabled == true)
                {
                    if (MyServoControlForm.DriveChanged == true)
                    {
                        MyServoControlForm.DriveChanged = false;
                        FTFSmartCarMessages.SetDriveServo MySetDriveMessage = new FTFSmartCarMessages.SetDriveServo();
                        MySetDriveMessage.MsgStruct.DrivingServoVal = MyServoControlForm.DriveServoVal;
                        MySetDriveMessage.MsgStruct.DrivingServoNeutral = MyServoControlForm.DriveServoNeutral;
                        MyCommunicationsManager.Write(MySetDriveMessage.ToByteArray());
                    }
                    if (MyServoControlForm.SteeringChanged == true)
                    {
                        MyServoControlForm.SteeringChanged = false;
                        FTFSmartCarMessages.SetSteeringServo MySetSteeringMessage = new FTFSmartCarMessages.SetSteeringServo();
                        MySetSteeringMessage.MsgStruct.SteeringServoNeutral = MyServoControlForm.SteeringServoNeutral;
                        MySetSteeringMessage.MsgStruct.SteeringServoVal = MyServoControlForm.SteeringServoVal;
                        MyCommunicationsManager.Write(MySetSteeringMessage.ToByteArray());
                    }
                }
            }
        }

        #endregion

        #region CHECK_INCOMING_MSGS

        void PostFirmwareVersionMessage(GlobalMessages.GetFirmwareMessage MyFirmwareMessage)
        {
            FirmwareVersionMajor = MyFirmwareMessage.MsgStruct.Major;
            FirmwareVersionMinor = MyFirmwareMessage.MsgStruct.Minor;
            FirmwareVersionRecieved = true;
        }

        void PostSystemStatusMessage(FTFSmartCarMessages.PostSystemState MyStatusMessagePost)
        {
            CurrentSystemState = MyStatusMessagePost.MsgStruct.CurrentSystemState;
        }

        void PostSensorDataHandler(FTFSmartCarMessages.PostSensorData MySensorData)
        {
            LastPotReading = MySensorData.MsgStruct.Pot;

            double VoltageIn = (((double)MySensorData.MsgStruct.Batt / 255.0) * 3.3)  *((9.01 + 4.12)/(4.12));
            MyBatteryViewer.PostNextVoltageReading(VoltageIn);
            LastRPMReading = MySensorData.MsgStruct.RPM;

            byte[] IRTemp = new byte[16];
            unsafe
            {
                fixed (byte* e = MySensorData.MsgStruct.IR)
                {
                    for (int i = 0; i < 16; i++)
                    {
                        IRTemp[i] = Convert.ToByte(e[i]);
                    }
                }
             }

            MyIRSensorViewer.PostIRSensorReadings(IRTemp);
            MyIR2d.PostNextIRData(IRTemp);

            double RPM = (1/(((double)MySensorData.MsgStruct.RPM) / ((double)HCS08_BUS_CLK) * 4))*60;
            
            MyRPMViewer.PostNextRPMReading(RPM);
        }

      

        void ParseIncomingMessages()
        {
            while (true)
            {
                Thread.Sleep(10);
                // update feed back upon receiving SYSTEM_STATS byte
                while (MyCommunicationsManager.MyPacketDetector.PacketQueue.Count > 0)
                {
                    byte[] InPacket = MyCommunicationsManager.MyPacketDetector.PacketQueue.Dequeue();

                    switch (InPacket[0])
                    {
                        case GlobalMessages.MessageCodes.MSG_REPORT_FIRMWARE_VERSION:

                            unsafe
                            {
                                if (InPacket.Length == sizeof(GlobalMessages.GetFirmwareMessage.MessageStructure))
                                {
                                    GlobalMessages.GetFirmwareMessage MyFirmwareMessage = new GlobalMessages.GetFirmwareMessage(InPacket);
                                    PostFirmwareVersionMessage(MyFirmwareMessage);
                                }
                            }
                            break;

                        case FTFSmartCarMessages.MessageCodes.MSG_POST_SYSTEM_STATE:
                            unsafe
                            {
                                if (InPacket.Length == sizeof(FTFSmartCarMessages.PostSystemState.MessageStructure))
                                {
                                    FTFSmartCarMessages.PostSystemState MyStatusMessagePost = new FTFSmartCarMessages.PostSystemState(InPacket);
                                    PostSystemStatusMessage(MyStatusMessagePost);
                                }
                            }

                            break;

                        case FTFSmartCarMessages.MessageCodes.MSG_POST_SENSOR_DATA:
                            unsafe
                            {
                                if (InPacket.Length == sizeof(FTFSmartCarMessages.PostSensorData.MessageStructure))
                                {
                                    FTFSmartCarMessages.PostSensorData MySensorMsg = new FTFSmartCarMessages.PostSensorData(InPacket);
                                    PostSensorDataHandler(MySensorMsg);
                                }
                            }

                        break;

                        case FTFSmartCarMessages.MessageCodes.MSG_POST_AUTO_NV_STATE_VARIABLES:

                        unsafe
                        {
                            if (InPacket.Length == sizeof(FTFSmartCarMessages.PostAutoNVStateVariables.MessageStructure))
                            {
                                FTFSmartCarMessages.PostAutoNVStateVariables AutoNVStateVariables = new FTFSmartCarMessages.PostAutoNVStateVariables(InPacket);
                                MyAutoNVState = AutoNVStateVariables;
                                MyControlViewerForm.PostNextControlVariablesReading(AutoNVStateVariables.MsgStruct.IRCentroid,
                                                                                    AutoNVStateVariables.MsgStruct.IRCentroidFiltered,
                                                                                    AutoNVStateVariables.MsgStruct.IRCentroidDerivative,
                                                                                    AutoNVStateVariables.MsgStruct.CommandedSteering,
                                                                                    AutoNVStateVariables.MsgStruct.CommandedDrive);
                            }
                        }

                        break;

                           
                    }
                }
            }
        }
   
        #endregion

        private void servoControlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MyServoControlForm.Show();
            MyServoControlForm.WindowState = FormWindowState.Normal;
            MyServoControlForm.Focus();

        }

        private void iRSensorViewerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MyIRSensorViewer.Show();
            MyIRSensorViewer.WindowState = FormWindowState.Normal;
            MyIRSensorViewer.Focus();
        }

        private void rPMViewerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MyRPMViewer.Show();
            MyRPMViewer.WindowState = FormWindowState.Normal;
            MyRPMViewer.Focus();
        }

        private void iR2dToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MyIR2d.Show();
            MyIR2d.WindowState = FormWindowState.Normal;
            MyIR2d.Focus();
        }

        private void autoNVControlVariablesViewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MyControlViewerForm.Show();
            MyControlViewerForm.WindowState = FormWindowState.Normal;
            MyControlViewerForm.Focus();
        }

        private void FTFSmartCarInterfaceSurfaceForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            ProcessMsgThread.Abort();
            MySystemControlForm.SaveFormSettings();
            MyCommunicationsManager.Terminate();
            Application.Exit();
            e.Cancel = false;
        }

        private void idealOutputViewerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MyBatteryViewer.Show();
            MyBatteryViewer.WindowState = FormWindowState.Normal;
            MyBatteryViewer.Focus();
        }
    
    }
} 